雖然我們的 App 為了怕麻煩,有要求 18+ 以上才能使用,但還是怕會有繞過這個限制的小孩
在一對一聊天的場景,可以傳圖片。雖然大部分都非常健全,但偶爾還是會出現色情圖片。
為了怕發生什麼對我們平台麻煩的事,我們決定要自動偵測是不是裸照,在搭配他們自己說的年齡(不等於實際年齡),如果有可能有十八歲以下,我們會自動跳出一個警告說如果有發現任何不法事宜會配合警察。
完成我們的需求的第一步,就是要有一個裸照分類器。這個應該是非常常見的需求,所有的用戶產生內容平台應該都有。我們一定沒必要自己做,而且自己做也不一定做得比別人好。所以我們就很自然的去 GitHub 上找已經訓練好的模型。
Github 上只要搜 "NSFW" (Not suitable for work,工作場合不宜) 就有非常多適合各種語言的現成模型。比如說
infinitered/nsfwjs: NSFW detection on the client-side via TensorFlow.js (github.com)
或是
GantMan/nsfw_model: Keras model of NSFW detector (github.com)
我們找了幾個 javascript 可以用的,做了簡單的評估。
評估用的資料集是 1200 張實際用戶傳的圖片,一半 positive(有裸露),一半 negative(正常)。
然後就簡單的測了一下 precision 跟 recall。
最後選了一個表現最佳的模型。
取的模型後,下一步是要加進 code 做實時判斷。
因為我們用是 tensorflow 的模型,我們就用了 tfjs 這個 library
https://www.npmjs.com/package/@tensorflow/tfjs
import '@tensorflow/tfjs';
import * as tfnode from '@tensorflow/tfjs-node';
核心部分的實作如下
tfnode.tidy(() => {
const tensor = tfnode.node.decodeImage(file.buffer, 3, 'int32');
const image = tfnode.image
.resizeBilinear(tensor, [IMAGE_SIZE, IMAGE_SIZE])
.mul(1.0 / 255.0)
.reshape([1, IMAGE_SIZE, IMAGE_SIZE, 3]);
const predictions = mobilenet.predict(image) as tfnode.Tensor;
const predictedData = predictions.dataSync();
const adultRatio = predictedData[3] + predictedData[4];
resolve(adultRatio);
});
因為傳圖片不是主要功能,頻率也不高,加了這個判斷,對效能的影響不大。
唯一一種情況我們有優化的是,我們發現有些人會一直傳同一張圖片,為了避免每次都重複判斷,判斷過的圖過我們會轉成 hash,把 hash 跟結果存在 DB 裡。如果以前有判斷過,就直接取用。
在做這個功能之前,曾經被抱怨過一兩次,但自從加了這個分類器跟警告之後,一年多來都沒有出現任何問題,所以我覺得這個功能有達到我們預期的效果了!
最新文章會分享在臉書:https://www.facebook.com/gigi.wuwu/
歡迎留言討論